home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1998 / MacHack 1998.toast / Sessions / Why Java Sucks / Newton11 / NewtonCanvas.java < prev    next >
Encoding:
Text File  |  1998-06-13  |  5.0 KB  |  293 lines  |  [TEXT/R*ch]

  1. /*
  2.     NewtonCanvas.java - A canvas for running a gravity simulation.
  3.  
  4.     Copyright (C) 1996-1997 by Michael J. Webb
  5. */
  6.  
  7. // Imports
  8.  
  9. import java.awt.Canvas;
  10. import java.awt.Dimension;
  11. import java.awt.Graphics;
  12. import java.awt.Image;
  13.  
  14. import java.io.DataInputStream;
  15. import java.io.InputStreamReader;
  16. import java.io.PrintStream;
  17. import java.io.StreamTokenizer;
  18.  
  19. import java.util.Date;
  20. import java.util.Vector;
  21.  
  22. import IdleTask;
  23. import TickerThread;
  24.  
  25. /** A canvas for running a gravity simulation.
  26.  */
  27. public class NewtonCanvas extends java.awt.Canvas
  28.     implements IdleTask
  29. {
  30.  
  31. /* Public members. */
  32.  
  33.     public int    myNumRocks;
  34.     public Rock[] myRocks;
  35.  
  36. /* Construction/Destruction Methods. */
  37.  
  38.     /** Default constructor - make 100 random rocks.
  39.      */
  40.     public NewtonCanvas()
  41.     {
  42.         this(100, new Dimension(400, 400));
  43.     }
  44.  
  45.     /** Randomizing constructor.  Make <theNumRocks> rocks.
  46.      */
  47.     public NewtonCanvas
  48.     (
  49.         int theNumRocks,
  50.         Dimension theSize
  51.     )
  52.     {
  53.         setSize(theSize);
  54.  
  55.         myNumRocks = theNumRocks;
  56.  
  57.         myRocks = new Rock[theNumRocks];
  58.  
  59.         for (int i = 0; i < theNumRocks; i++)
  60.         {
  61.             myRocks[i] = new Rock(i, this);
  62.         }
  63.  
  64.     }
  65.  
  66. /* Public Methods. */
  67.  
  68.     /** Reseed the canvas with a new population of random rocks.
  69.      */
  70.     public void reseed()
  71.     {
  72.         for (int i = 0; i < myNumRocks; i++)
  73.         {
  74.             Rock.seed(myRocks[i]);
  75.         }
  76.  
  77.         redraw(getGraphics());
  78.     }
  79.  
  80.     /** Set the naughty flag of the canvas.  Abuses garbage collection.
  81.      */
  82.     public void setNaughty(boolean naughty)
  83.     {
  84.         fNaughty = naughty;
  85.     }
  86.  
  87.     /** Start the gravity simulation.
  88.      */
  89.     public synchronized void startTask()
  90.     {
  91.         fTime = new Date();
  92.  
  93.         if (fTicker == null)
  94.         {
  95.             fTicker = new TickerThread(this);
  96.             fTicker.start();
  97.         }
  98.     }
  99.  
  100.     /** Stop the gravity simulation.
  101.      */
  102.     public synchronized void stopTask()
  103.     {
  104.         if (fTicker != null)
  105.         {
  106.             fTicker.stop();
  107.             fTicker = null;
  108.         }
  109.     }
  110.  
  111.     /** Every time the simulation gets time, compute a new frame.
  112.      */
  113.     public synchronized void idle()
  114.     {
  115.         if (fRunning)
  116.         {
  117.             update(getGraphics());
  118.         }
  119.     }
  120.  
  121.     /** Pause the simulation.
  122.      */
  123.     public void pause()
  124.     {
  125.         fRunning = false;
  126.     }
  127.  
  128.     /** Resume the simulation.
  129.      */
  130.     public void resume()
  131.     {
  132.         fTime = new Date();
  133.         fFrames = 0;
  134.  
  135.         fRunning = true;
  136.     }
  137.  
  138.     /** Compute the next frame of the simulation.
  139.      */
  140.     public void update(Graphics g)
  141.     {
  142.         // Compute new locations.
  143.         for (int i = 0; i < myNumRocks; i++)
  144.         {
  145.             myRocks[i].computeValues();
  146.         }
  147.  
  148.         // Redraw the canvas.
  149.  
  150.         redraw(g);
  151.  
  152.         // Update frame count.
  153.         fFrames += 1;
  154.     }
  155.  
  156.     /** Redraw the canvas.
  157.      */
  158.     public void redraw(Graphics g)
  159.     {
  160.         java.awt.Dimension d = getSize();
  161.  
  162.         // Check for resize.
  163.         if (fOffScreenImage != null)
  164.         {
  165.             if
  166.                     (
  167.                         (fOffScreenImage.getHeight(this) != d.height) ||
  168.                         (fOffScreenImage.getWidth(this) != d.width)
  169.                     )
  170.             {
  171.                 fOffScreenImage = null;
  172.             }
  173.         }
  174.  
  175.         // Build offscreen image, if necessary.
  176.         if ((fOffScreenImage == null) || fNaughty)
  177.         {
  178.             fOffScreenImage = createImage(d.width,d.height);
  179.         }
  180.  
  181.         // Setup the offscreen graphics.
  182.         fOffScreenGraphics = fOffScreenImage.getGraphics();
  183.         fOffScreenGraphics.setColor(getBackground());
  184.         fOffScreenGraphics.fillRect(0,0,d.width,d.height);
  185.  
  186.         // Draw the rocks.
  187.         for (int i = 0; i < myNumRocks; i++)
  188.         {
  189.             myRocks[i].drawSelfShape(fOffScreenGraphics);
  190.         }
  191.  
  192.         // Move offscreen to screen.
  193.         g.drawImage(fOffScreenImage, 0, 0, null);
  194.     }
  195.  
  196.     /** Give the simulation's minimum size.
  197.      */
  198.     public java.awt.Dimension getMinimumSize()
  199.     {
  200.         return (new java.awt.Dimension(100, 100));
  201.     }
  202.  
  203.     /** Give the simulation's preferred size.
  204.      */
  205.     public java.awt.Dimension getPreferredSize()
  206.     {
  207.         return (new java.awt.Dimension(400, 400));
  208.     }
  209.  
  210.     /** Frame count accessor.
  211.      */
  212.     public long getFrames() { return fFrames; }
  213.  
  214.     /** Frame rate accessor.
  215.      */
  216.     public double getFrameRate()
  217.     {
  218.         double rate = 0.0;
  219.         Date    time = new Date();
  220.         long    elapsed = 0;
  221.  
  222.         if (fTime != null)
  223.         {
  224.             elapsed = time.getTime() - fTime.getTime();
  225.         }
  226.  
  227.         if (elapsed != 0)
  228.         {
  229.             rate = ((double)fFrames) * 1000.0 / ((double)elapsed);
  230.         }
  231.  
  232.         return rate;
  233.     }
  234.  
  235.     /** Save a simulation.
  236.      */
  237.     public void store(java.io.PrintStream stream)
  238.     {
  239.         for (int i = 0; i < myNumRocks; i++)
  240.         {
  241.             myRocks[i].store(stream);
  242.         }
  243.     }
  244.  
  245.     /** Restore a simulation.
  246.      */
  247.     public void restore(java.io.DataInputStream stream)
  248.     {
  249.         Vector rockVector = new Vector(100, 10);
  250.         Rock newRock = null;
  251.         boolean reading = true;
  252.         int rockCount = 0;
  253.  
  254.         InputStreamReader theReader = new InputStreamReader(stream);
  255.         StreamTokenizer tokens = new StreamTokenizer(theReader);
  256.  
  257.         tokens.parseNumbers();
  258.  
  259.         while (reading)
  260.         {
  261.             try
  262.             {
  263.                 newRock = new Rock(rockCount, this);
  264.                 newRock.restore(tokens);
  265.                 rockCount += 1;
  266.                 rockVector.addElement(newRock);
  267.             }
  268.             catch (Throwable e)
  269.             {
  270.                 reading = false;
  271.             }
  272.         }
  273.  
  274.         myNumRocks = rockVector.size();
  275.         myRocks = new Rock[myNumRocks];
  276.         rockVector.copyInto(myRocks);
  277.     }
  278.  
  279. /* Private members. */
  280.  
  281.     private TickerThread    fTicker = null;
  282.     private boolean            fYield = false;
  283.  
  284.     private Image            fOffScreenImage = null;
  285.     private Graphics        fOffScreenGraphics = null;
  286.  
  287.     private long            fFrames = 0;
  288.     private Date            fTime = null;
  289.  
  290.     private boolean            fRunning = true;
  291.     private boolean            fNaughty = false;
  292. }
  293.